package multi_thread.advanced.concurrent_collection;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author Cheng Jun
 * Description: 无锁、无界、非阻塞式的线程安全队列
 * 无锁: 使用 CAS机制 进行出列和入列操作。
 * 无界：因为底层是 Node 单项链表，所以只要内存够，元素就能一直入列。
 * 无阻塞：因为使用 CAS自旋，所以各个线程之间不受影响，仅自旋的次数不同。
 * 线程安全：CAS + volatile 保证线程安全。Node节点的 item和 next 都被 volatile修饰
 * ConcurrentLinkedQueue 是一个 利用CAS自旋实现无锁、无阻塞的线程安全，底层利用单向链表存储队列元素实现无界 的队列。
 * 所以它还是个队列，Concurrent 表示保证并发的要求，Linked 表示底层利用链表存储元素。
 * ConcurrentLinkedQueue 的应用场景有哪些？
 * 缺点：ConcurrentLinkedQueue 的无界特性，使得Programmer 容易造成内存溢出OOM。
 * @version 1.0
 * @date 2021/10/14 20:47
 * @see ConcurrentLinkedQueue
 * 重点掌握
 */
public class ConcurrentLinkedQueueExample {

    public static void main(String[] args) {
        ConcurrentLinkedQueue<String> ticketQueue = new ConcurrentLinkedQueue<>();
        ConcurrentLinkedQueue<String> ticketQueue1 = new ConcurrentLinkedQueue<>();
        // add 是 Collection接口的抽象方法，offer 是Queue接口的抽象方法。
        // add 在队列满了后再插入会抛出异常。ConcurrentLinkedQueue是无界的，不受影响
        ticketQueue.add("xm");
        ticketQueue.add("lw");
        ticketQueue.offer("cauchy");
        // ticketQueue.offer(null);
        // peek 是查看头元素，poll 是出列操作，也可以获取头元素，并且头元素会出列。
        System.out.println("ticketQueue.peek() = " + ticketQueue.peek());
        System.out.println("ticketQueue.size() = " + ticketQueue.size());
        System.out.println("ticketQueue.poll() = " + ticketQueue.poll());
        System.out.println("ticketQueue.size() = " + ticketQueue.size());
        // 不要在 生产环境使用这个方法，因为时间复杂度 是 O(n)
        ticketQueue.size();
    }
}
